home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Applications / Eudora 1.3.1 / source / squish.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-16  |  5.7 KB  |  216 lines  |  [TEXT/MPS ]

  1. #define FILE_NUM 44
  2. #pragma load EUDORA_LOAD
  3. #pragma segment Squish
  4.     Boolean NeedsCompaction(long dirId, UPtr name);
  5. /************************************************************************
  6.  * DoCompact - compact all mailboxes
  7.  ************************************************************************/
  8. void DoCompact(long dirId,HFileInfo *hfi,short suffixLen)
  9. {
  10.     typedef struct
  11.         {Str31 name; Boolean isDir; long dirId;} NameType, *NamePtr, **NameHandle;
  12.     NameType thisOne;
  13.     NameHandle names;
  14.     short count=0,item;
  15.  
  16.     /*
  17.      * close all windows
  18.      */
  19.     if (dirId==MyDirId && !CloseAll()) return;
  20.     
  21.     /*
  22.      * get started
  23.      */
  24.     if ((names=NuHandle(0L))==nil)
  25.         DieWithError(ALLO_MBOX_LIST,MemError());
  26.     
  27.     /*
  28.      * read names of mailbox files
  29.      */
  30.     hfi->ioNamePtr = thisOne.name;
  31.     hfi->ioFDirIndex = 0;
  32.     for (thisOne.dirId=dirId;!DirIterate(MyVRef,dirId,hfi);thisOne.dirId=dirId)
  33.     {
  34.         if (thisOne.isDir = 0!=(hfi->ioFlAttrib&0x10))
  35.             thisOne.dirId = hfi->ioDirID;
  36.         else
  37.         {
  38.             if (hfi->ioFlFndrInfo.fdType!=TOC_TYPE) continue;
  39.             *thisOne.name -= suffixLen;                    /* remove suffix */
  40.             thisOne.name[*thisOne.name+1] = 0;    /* null-terminate */
  41.         }
  42.         PtrAndHand (&thisOne,names,sizeof(thisOne));
  43.         if (MemError()) DieWithError(ALLO_MBOX_LIST,MemError());
  44.         count++;
  45.         loop:;
  46.     }
  47.     
  48.     if (dirId==MyDirId) OpenProgress();
  49.     for (item=0;item<count;item++)
  50.     {
  51.         GiveTime();
  52.         thisOne = (*names)[item];
  53.         Progress(NoChange,thisOne.name);
  54.         if (thisOne.isDir)
  55.             DoCompact(thisOne.dirId,hfi,suffixLen);
  56.         else if (NeedsCompaction(thisOne.dirId,thisOne.name))
  57.             CompactMailbox(thisOne.dirId,thisOne.name);
  58.     }
  59.     if (dirId==MyDirId) CloseProgress();
  60.     DisposHandle(names);
  61. }
  62.  
  63. /************************************************************************
  64.  * NeedsCompaction - see if a toc and a mailbox are in perfect agreement
  65.  ************************************************************************/
  66. Boolean NeedsCompaction(long dirId, UPtr name)
  67. {
  68.     TOCHandle tocH;
  69.     short mNum;
  70.     long offset = 0;
  71.     Boolean need=False;
  72.     long eof;
  73.     HFileInfo info;
  74.         
  75.     if (tocH=TOCByName(dirId,name))
  76.     {
  77.         for (mNum=0; mNum<(*tocH)->count; mNum++)
  78.             if ((*tocH)->sums[mNum].offset != offset)
  79.             {
  80.                 need = True;
  81.                 break;
  82.             }
  83.             else
  84.                 offset += (*tocH)->sums[mNum].length;
  85.         
  86.         if (!need)
  87.         {
  88.             if (!HGetFileInfo((*tocH)->vRef,dirId,name,&info) &&
  89.                     info.ioFlLgLen!=offset && !BoxFOpen(tocH))
  90.             {
  91.                 if (!GetEOF((*tocH)->refN,&eof))
  92.                 {
  93.                     SetEOF((*tocH)->refN,offset);
  94.                     (*tocH)->dirty = True;
  95.                 }
  96.                 BoxFClose(tocH);
  97.             }
  98.         }
  99.         
  100.         if (!need && !(*tocH)->win->qWindow.visible) CloseMyWindow((*tocH)->win);
  101.     }
  102.     return(need);
  103. }
  104.  
  105. /************************************************************************
  106.  * CompactMailbox - rewrite a mailbox to agree with a table of contents
  107.  ************************************************************************/
  108. void CompactMailbox(long dirId, UPtr name)
  109. {
  110.     TOCHandle tocH=nil;
  111.     short oldRefN=0, newRefN=0;
  112.     Str31 tmpName;
  113.     Str31 tmpSuffix;
  114.     long size=0;
  115.     short mNum;
  116.     int err=0;
  117.     int rnErr=0;
  118.     FInfo info;
  119.     short newVRef;
  120.     long newDirId;
  121.     HFileInfo hfi;
  122.         
  123.     CycleBalls();
  124.     GetRString(tmpSuffix,TEMP_SUFFIX);
  125.     PCopy(tmpName,name);
  126.     PCat(tmpName,tmpSuffix);
  127.     
  128.     if ((tocH=TOCByName(dirId,name))==nil) goto done;
  129.     
  130.     if (err=BoxFOpen(tocH)) goto done;
  131.     oldRefN = (*tocH)->refN;
  132.     newVRef=(*tocH)->vRef;newDirId=(*tocH)->dirId;
  133.     if (err=MyResolveAlias(&newVRef,&newDirId,name,nil)) goto done;
  134.     if (!HGetFileInfo(newVRef,newDirId,tmpName,&hfi) && hfi.ioFlLgLen)
  135.         {FileSystemError(SQUISH_LEFTOVERS,tmpName,dupFNErr); goto done;}
  136.     if (err=MakeResFile(tmpName,newVRef,newDirId,CREATOR,MAILBOX_TYPE))
  137.         {FileSystemError(COULDNT_SQUEEZE,name,err); goto done;}
  138.     if (err=FSHOpen(tmpName,newVRef,newDirId,&newRefN,fsRdWrPerm))
  139.         {FileSystemError(COULDNT_SQUEEZE,name,err); goto done;}
  140.  
  141.     /*
  142.      * figure out how big it should be
  143.      */
  144.     for (mNum=0;mNum<(*tocH)->count;mNum++)
  145.         size += (*tocH)->sums[mNum].length;
  146.     if (err=MyAllocate(newRefN,size))
  147.         {FileSystemError(COULDNT_SQUEEZE,name,err); goto done;}
  148.  
  149.     size = 0;
  150.     for (mNum=0;mNum<(*tocH)->count;mNum++)
  151.     {
  152.       CycleBalls();
  153.         if ((err=CopyFBytes(oldRefN,(*tocH)->sums[mNum].offset,
  154.                 (*tocH)->sums[mNum].length,newRefN,size)))
  155.             {FileSystemError(COULDNT_SQUEEZE,name,err); goto done;}
  156.         (*tocH)->sums[mNum].offset = size;
  157.         size += (*tocH)->sums[mNum].length;
  158.     }
  159.     if (mNum>=(*tocH)->count)
  160.     {
  161.         /* success! */
  162.         FSClose(newRefN); newRefN = 0;
  163.         FSClose(oldRefN); oldRefN = 0;
  164.         (*tocH)->refN = 0;
  165.         
  166.         /* now, copy the resource fork */
  167.         (void) CopyRFork(newVRef,newDirId,tmpName,
  168.                             (*tocH)->vRef,(*tocH)->dirId,name);
  169.         HGetFInfo(newVRef,newDirId,name,&info);
  170.         
  171.         /* do the deed */
  172.         if (err=HDelete(newVRef,newDirId,name))
  173.             {FileSystemError(COULDNT_SQUEEZE,name,err); goto done;}
  174.         if (rnErr=err=HRename(newVRef,newDirId,tmpName,name))
  175.             FileSystemError(BAD_COMP_RENAME,tmpName,err);
  176.         HSetFInfo(newVRef,newDirId,name,&info);
  177.     }
  178.     
  179. done:
  180.     if (newRefN) FSClose(newRefN);
  181.     if (oldRefN) {FSClose(oldRefN); (*tocH)->refN = 0;}
  182.     if (tocH)
  183.     {
  184.         (*tocH)->dirty = err==0;
  185.         (*tocH)->totalK = (*tocH)->usedK;    /* let's not do this again, shall we? */
  186.         CloseMyWindow((*tocH)->win);
  187.     }
  188.     if (err && !rnErr) HDelete(newVRef,newDirId,tmpName);
  189. }
  190.  
  191.  
  192. /************************************************************************
  193.  * NeedAutoCompact - should we compact this mailbox?
  194.  ************************************************************************/
  195. Boolean NeedAutoCompact(TOCHandle tocH)
  196. {
  197.     long waste = ((*tocH)->totalK-(*tocH)->usedK)K;
  198.     
  199.     /*
  200.      * is there room to do it?
  201.      */
  202.     if ((*tocH)->volumeFree < ((*tocH)->usedK+10)K) return (False);
  203.     
  204.     /*
  205.      * is there too much waste space?
  206.      */
  207.     if ((100*waste)/((*tocH)->totalK K + 1) > GetRLong(COMPACT_WASTE_PER)) return(True);
  208.     
  209.     /*
  210.      * are we too close to the disk limit?
  211.      */
  212.     if ((100*waste)/(*tocH)->volumeFree > GetRLong(COMPACT_FREE_PER)) return(True);
  213.         
  214.     return(False);
  215. }
  216.